`timescale 1ns / 1ns
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    20:28:30 07/09/2013 
// Design Name: 
// Module Name:    field_spliter 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
`define PMAP_LEN 50
module field_spliter(
    input rst_n,
    input clk,
    input valid_1_2,
    input [7:0] data_1_2,
    input msg_end_1_2,
    output reg valid_2_3,
    output reg [7:0] data_2_3,
    output reg [`PMAP_LEN - 1:0] sel_2_3,
    output reg [3:0] field_counter_2_3,
    output reg msg_end_2_3
    );
    
    parameter NEW_PMAP = 2'b00;
    parameter FILL_PMAP = 2'b01;
    parameter NEW_FIELD = 2'b10;
    parameter FILL_FIELD = 2'b11;
    
   // wire stopbit;
    reg [1:0] state;
    reg [1:0] nextstate;
    wire [6:0] data_r;
    
    reg [3:0] counter;
    reg [`PMAP_LEN - 1:0] pmap;
    reg [`PMAP_LEN - 1:0] sel;
    reg [`PMAP_LEN - 1:0] pmap_next;
    wire [`PMAP_LEN - 1:0] sel_next;
    reg valid_next;
    //wire [`PMAP_LEN - 1:0] sel_tmp;
    
//    assign stopbit = valid_1_2 & data[7];

    //assign sel_2_3 = sel;
    //assign field_counter_2_3 = counter;
    assign data_r = {data_1_2[0],data_1_2[1],data_1_2[2],data_1_2[3],
                     data_1_2[4],data_1_2[5],data_1_2[6]};
    assign sel_next = pmap_next & ((~pmap_next)+1);
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            msg_end_2_3 <= 1'b0;
        else
            msg_end_2_3 <= msg_end_1_2;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            data_2_3 <= 8'b0;
        else
            data_2_3 <= {1'b0,data_1_2};
    end
    
    always @( state or valid_1_2 or data_1_2 or msg_end_1_2 )
    begin
        case(state)
            NEW_PMAP:
                valid_next = 1'b0;
            FILL_PMAP:
                valid_next = 1'b0;
            NEW_FIELD:
                valid_next = valid_1_2;
            FILL_FIELD:
                valid_next = valid_1_2;
        endcase
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            valid_2_3 <= 1'b0;
        else
            valid_2_3 <= valid_next;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            sel <= `PMAP_LEN'b0;
        else
            sel <= sel_next;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            state <= NEW_PMAP;
        else
            state <= nextstate;
    end
    
    always @( state or valid_1_2 or data_1_2 or msg_end_1_2 )
    begin
        if(msg_end_1_2)
            nextstate = NEW_PMAP;
        else if(valid_1_2)
		  begin 
		      if( data_1_2[7] )
                nextstate = NEW_FIELD;
            else
            begin
                case(state)
                    NEW_PMAP:
                        nextstate = FILL_PMAP;
                    FILL_PMAP:
                        nextstate = FILL_PMAP;
                    NEW_FIELD:
                        nextstate = FILL_FIELD;
                    FILL_FIELD:
                        nextstate = FILL_FIELD;
                endcase
				end
        end
		  else
		      nextstate = state;
    end
    
    always @( state or data_1_2 or valid_1_2 or pmap or counter or sel or data_r )
    begin
        if(valid_1_2)
        begin
            case(state)
                NEW_PMAP:
                    pmap_next = {43'b0,data_r[6:0]};
                FILL_PMAP:
                    case( counter )
                        4'd1:
                            pmap_next = {36'b0, data_r[6:0], pmap[6:0]};
                        4'd2:
                            pmap_next = {29'b0, data_r[6:0], pmap[13:0]};
                        4'd3:
                            pmap_next = {22'b0, data_r[6:0], pmap[20:0]};
                        4'd4:
                            pmap_next = {15'b0, data_r[6:0], pmap[27:0]};
                        4'd5:
                            pmap_next = {8'b0, data_r[6:0], pmap[34:0]};
                        4'd6:
                            pmap_next = {1'b0, data_r[6:0], pmap[41:0]};
                        4'd7:
                            pmap_next = {data_r[0], pmap[48:0]};
                        default:
                            pmap_next = pmap;
                    endcase
                default:
                    if( data_1_2[7] )
                        pmap_next = pmap ^ sel;
                    else
                        pmap_next = pmap;
            endcase
        end
        else
            pmap_next = pmap;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            pmap <= `PMAP_LEN'b0;
        else
            pmap <= pmap_next;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            counter <= 4'b0;
        else
        begin
            if(nextstate == NEW_PMAP || nextstate == NEW_FIELD)
                counter <= 4'b0;
            else if(valid_1_2)
                counter <= counter + 4'b1;
        end
    end
	 
	 always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            field_counter_2_3 <= 4'b0;
        else
            field_counter_2_3 <= counter;
    end
	 
	 always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            sel_2_3 <= 50'b0;
        else
            sel_2_3 <= sel;
    end

endmodule
